package com.pfdu.simplescheduler.schedule;

import com.pfdu.simplescheduler.common.Task;
import com.pfdu.simplescheduler.config.SimpleSchedulerConfig;
import com.pfdu.simplescheduler.repo.TaskRepo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalTime;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Component
public class TaskCleaner {
    @Autowired
    private TaskRepo taskRepo;

    private Thread taskCleanerThread;

    private Boolean shutdown = false;

    @Autowired
    private SimpleSchedulerConfig config;

    class Cleaner implements Runnable {
        @Override
        public void run() {
            log.info("TaskCleaner is started.");
            int sleepTime = 0;
            try {
                while (!shutdown) {
                    // 只能每天 20点至23点 之间可以执行清理任务
                    if (!canInvoke()) {
                        Thread.sleep(60 * 1000);
                        continue;
                    }

                    // 删除 任务表 中过期的任务（过期的任务：status是“已完成”并且update_time与本次清理时的时刻之间的时长超过了指定时长）
                    List<Task> taskList = taskRepo.listCanClean();
                    if (taskList != null && taskList.size() > 0) {
                        log.debug(String.format("TaskCleaner cleans tasks[%s]", taskList.stream().map(task -> task.getId()).collect(Collectors.toList())));
                        taskRepo.deleteExpired(taskList);
                        sleepTime = 0;
                    } else {
                        sleepTime++;
                        sleepTime = sleepTime >= 60 ? 60 : sleepTime;
                        Thread.sleep(sleepTime * 1000); // 没有需要清理的任务，就不要让线程空转。
                    }
                }
            } catch (InterruptedException e) {
                log.warn("TaskCleaner is interrupted while sleeping.");
            } catch (Throwable t) {
                log.error("TaskCleaner is error：", t);
            }
            log.info("TaskCleaner is stopped.");
        }

        private boolean canInvoke() {
            LocalTime start = LocalTime.parse(config.getCleanStartTime());
            LocalTime stop = LocalTime.parse(config.getCleanStopTime());
            LocalTime now = LocalTime.now();
            return now.isAfter(start) && now.isBefore(stop);
        }
    }

    public void start(){
        taskCleanerThread = new Thread(new Cleaner());
        taskCleanerThread.start();
    }

    public void stop() {
        this.shutdown = true;
        taskCleanerThread.interrupt();
    }
}
